package club.monkeywood.transaction.ticket.service;

import club.monkeywood.transaction.ticket.dao.TicketRepository;
import club.monkeywood.transaction.ticket.dto.OrderDTO;
import club.monkeywood.transaction.ticket.vo.Ticket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Slf4j
public class TicketService {

    @Autowired
    private TicketRepository ticketRepository;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Transactional
    @RabbitListener(queuesToDeclare = @Queue("order:new"))
    public void handleTicketLock(OrderDTO orderDTO){
        log.info("收到新订单:{}-----------------------------------", orderDTO);
        int lockCount = ticketRepository.lockTicket(orderDTO.getCustomerId(),
                orderDTO.getTicketNum());
        if(lockCount==1){
            log.info("锁定成功-------------------------------------");
            orderDTO.setStatus("TICKET_LOCKED");
            amqpTemplate.convertAndSend("order:lock", orderDTO);
        }
        else{
            log.info("锁定失败-------------------------------------");
            orderDTO.setStatus("TICKET_LOCK_FAIL");
            amqpTemplate.convertAndSend("order:fail", orderDTO);
        }
    }

    @Transactional
    @RabbitListener(queuesToDeclare = @Queue("order:ticket_move"))
    public void handleTicketMove(OrderDTO dto){
        log.info("Get new order for ticket move:{}", dto);

        int count = ticketRepository.moveTicket(dto.getCustomerId(), dto.getTicketNum());
        if(count==0){
            log.warn("Ticket already moved:{}",dto);
        }
        dto.setStatus("TICKET_MOVED");
        amqpTemplate.convertAndSend("order:finish",dto);
    }

    @Transactional
    @RabbitListener(queuesToDeclare = @Queue("order:ticket_unmove"))
    public void handleUnMove(OrderDTO dto){
        log.info("Get new order for ticket unmove:{}", dto);

        int count = ticketRepository.unmoveTicket(dto.getTicketNum());
        if(count==0){
            log.warn("Ticket already unmoved, or not moved:{}",dto);
        }
        dto.setStatus("TICKET_UNMOVED");
        amqpTemplate.convertAndSend("order:fail",dto);
    }

    @Transactional
    @RabbitListener(queuesToDeclare = @Queue("order:ticket_error"))
    public void handleTicketUnlock(OrderDTO dto){
        log.info("unlock ticket，order:{}", dto);

        int count = ticketRepository.unlockTicket(dto.getTicketNum());
        if(count == 0){
            log.info("Ticket already unlocked.",dto);
        }
        amqpTemplate.convertAndSend("order:fail", dto);
    }


    //更新记录时，没有加票的状态判断，导致高并发重复更新
    @Transactional
    public Ticket ticketLock(OrderDTO orderDTO){
        Ticket ticket = ticketRepository.findByTicketNum(orderDTO.getTicketNum());
        ticket.setLockUser(orderDTO.getCustomerId());
        Ticket save = ticketRepository.save(ticket);

        try {
            Thread.sleep(10*1000);
        } catch (InterruptedException e) {
            log.error(e.getMessage());
        }

        return save;
    }

    //update语句有数据库锁，可避免高并发重复更新
    //第2条更新语句执行时，票的状态已被更新，不能再被修改
    @Transactional
    public int ticketLock2(OrderDTO orderDTO){
        int count = ticketRepository.lockTicket(orderDTO.getCustomerId(),
                orderDTO.getTicketNum());
        log.info("lock ticket count:{}",count);
        try {
            Thread.sleep(10*1000);
        } catch (InterruptedException e) {
            log.error(e.getMessage());
        }
        return count;
    }

}
